use loco_rs::prelude::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

pub use super::_entities::customer_group_translations::{self, ActiveModel, Entity, Model};

#[derive(Debug, Deserialize, Serialize)]
pub struct CreateParams {
    pub customer_group_id: String,
    pub locale: String,
    pub name: String,
    pub description: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct UpdateParams {
    pub customer_group_id: Option<String>,
    pub locale: Option<String>,
    pub name: Option<String>,
    pub description: Option<String>,
}

#[async_trait::async_trait]
impl ActiveModelBehavior for super::_entities::customer_group_translations::ActiveModel {
    async fn before_save<C>(self, _db: &C, insert: bool) -> Result<Self, DbErr>
    where
        C: ConnectionTrait,
    {
        if insert {
            let mut this = self;
            this.id = ActiveValue::Set(Uuid::new_v4().to_string());
            Ok(this)
        } else {
            Ok(self)
        }
    }
}

impl Model {
    pub async fn create(db: &DatabaseConnection, params: CreateParams) -> ModelResult<Self> {
        let active_model = ActiveModel {
            customer_group_id: ActiveValue::Set(params.customer_group_id),
            locale: ActiveValue::Set(params.locale),
            name: ActiveValue::Set(params.name),
            description: ActiveValue::Set(params.description),
            ..Default::default()
        };

        let model = active_model.insert(db).await?;
        Ok(model)
    }

    pub async fn update_by_id(
        db: &DatabaseConnection,
        id: &str,
        params: UpdateParams,
    ) -> ModelResult<Self> {
        let translation = Self::find_by_id(db, id).await?;
        let mut active_model: ActiveModel = translation.into();

        if let Some(customer_group_id) = params.customer_group_id {
            active_model.customer_group_id = ActiveValue::Set(customer_group_id);
        }

        if let Some(locale) = params.locale {
            active_model.locale = ActiveValue::Set(locale);
        }

        if let Some(name) = params.name {
            active_model.name = ActiveValue::Set(name);
        }

        if let Some(description) = params.description {
            active_model.description = ActiveValue::Set(Some(description));
        }

        let model = active_model.update(db).await?;
        Ok(model)
    }

    pub async fn find_by_id(db: &DatabaseConnection, id: &str) -> ModelResult<Self> {
        let translation = Entity::find_by_id(id).one(db).await?;
        translation.ok_or_else(|| ModelError::EntityNotFound)
    }

    pub async fn delete_by_id(db: &DatabaseConnection, id: &str) -> ModelResult<()> {
        let translation = Self::find_by_id(db, id).await?;
        let _result = Entity::delete_by_id(translation.id).exec(db).await?;
        Ok(())
    }

    pub async fn find_by_group(db: &DatabaseConnection, group_id: &str) -> ModelResult<Vec<Self>> {
        let translations = Entity::find()
            .filter(customer_group_translations::Column::CustomerGroupId.eq(group_id))
            .all(db)
            .await?;
        Ok(translations)
    }

    pub async fn find_by_locale(db: &DatabaseConnection, locale: &str) -> ModelResult<Vec<Self>> {
        let translations = Entity::find()
            .filter(customer_group_translations::Column::Locale.eq(locale))
            .all(db)
            .await?;
        Ok(translations)
    }
}
